class Compiler {
	constructor(vm) {
		this.el = vm.$el;
		this.vm = vm;
		this.methodsList = vm.$options.methods;//添加方法
		this.compile(this.el)
	}

	compile(el) {
		let childNodes = el.childNodes;
		Array.from(childNodes).forEach(node => {
			//处理文本节点
			if(this.isTextNode(node)) {
				this.compileText(node)
			} else if(this.isElementNode(node)) {
				this.compileElement(node)
			}
			//判断node节点，是否有子节点，如果有子节点，要递归调用compile
			if(node.childNodes && node.childNodes.length) {
				this.compile(node)
			}
		})
	}
	//处理文本节点
	compileText(node) {
		let reg = /\{\{(.+?)\}\}/
		let value = node.textContent;
		if(reg.test(value)) {
			let key = RegExp.$1.trim();
			node.textContent = value.replace(reg, this.vm[key])
			new Watcher(this.vm, key, (newValue) => {
				node.textContent = newValue;
			})
		}
	}
	//编译元素节点，处理指令
	compileElement(node) {
		Array.from(node.attributes).forEach(attr => {
			//判断是否是指令
			let attrName = attr.name;
			if(this.isDirectve(attrName)) {
				//v-text 
				attrName = attrName.substr(2)
				let key = attr.value.trim()
				//叫onUpdater感觉很奇怪
				if(attrName.startsWith('on')){
					this.onaddEvent(attrName,key,node)
				}else{
					this.update(node, key, attrName)
				}
			}
		})
	}
	//判断元素属性是否是指令
	isDirectve(attrName) {
		return attrName.startsWith('v-')
	}
	update(node, key, attrName) {
		let updateFn = this[attrName + "Updater"]
		updateFn && updateFn.call(this,node,key,this.vm[key])
	}
	//处理v-text指令
	 textUpdater(node,key,value) {
		node.textContent = value
		new Watcher(this.vm, key, (newValue) => {
			node.textContent = newValue;
		})
	}
	 //处理v-on
	 onaddEvent(attrName,key,node){
	 	let methodsList = this.methodsList;//获取点击事件对象
//	 	click(点击) mouseenter（进入）、mouseover（逗留）、mouseout（暂离）、mouseleave（离开）等等
	 	let [click,$=''] = attrName = attrName.substr(3).split(".");//获取修饰符合点击事件类型click mouse.....
		
	 	let reg = /(.+?)\((.+?)\)/g;   // 获取方法名和参数
	 	if(reg.test(key)){
	 		let Fnname = RegExp.$1.trim();	//方法名
	 		let parameter = RegExp.$2.trim();//方法参数
	 		console.log(methodsList[Fnname])
			if(methodsList[Fnname]){//存在方法
				node.addEventListener('click',(event)=>{
					if($){
						let myevent = event || window.event;
						this.setModifier($,myevent)	
					}						
					methodsList[Fnname].call(this.vm,parameter)
				})				
			}
	 	
	 	}	
	 }
	//处理v-html指令
	 htmlUpdater(node,key,value){
		node.innerHTML = value
		new Watcher(this.vm, key, (newValue) => {
			node.innerHTML = newValue;
		})	 	
	 }
	//处理v-model指令
	modelUpdater(node,key,value) {
		node.value = value
		new Watcher(this.vm, key, (newValue) => {
			node.value = newValue;
		})
		node.addEventListener('input',()=>{
			this.vm[key] = node.value 
		})
	}
	 //设置修饰符
	 setModifier($,myevent){
		//	. - 调用 event.stopPropagation()。
		//	.prevent - 调用 event.preventDefault()。
		//	.capture - 添加事件侦听器时使用 capture 模式。
		//	.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
		//	.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
		//	.native - 监听组件根元素的原生事件。
		//	.once - 只触发一次回调。
		//	.left - (2.2.0) 只当点击鼠标左键时触发。
		//	.right - (2.2.0) 只当点击鼠标右键时触发。
		//	.middle - (2.2.0) 只当点击鼠标中键时触发。
		//	.passive - (2.3.0) 以 { passive: true } 模式添加侦听器	 	
	 	switch ($){
	 		case 'stop':
	 			myevent.stopPropagation()
	 			break;
	 		case 'prevent':
	 			myevent.preventDefault()
	 			break;	 			
	 		default:
	 			break;
	 	}
	 }	
	//判断节点是否是文本节点
	isTextNode(node) {
		return node.nodeType === 3
	}
	//判断节点是否是元素节点
	isElementNode(node) {
		return node.nodeType === 1
	}
}